package cz.muni.fi.pa165.library.backend;

import java.util.List;
import javax.persistence.EntityManager;
import javax.persistence.NoResultException;
import javax.persistence.NonUniqueResultException;
import javax.persistence.PersistenceContext;
import java.math.BigInteger;
import java.security.MessageDigest;

/**
 *
 * @author Matúš Abaffy
 */
public class ReaderDAOImpl implements ReaderDAO {

    @PersistenceContext(name = "LibraryPU")
    private EntityManager entityManager;

    public void setEntityManager(EntityManager entityManager) {
        this.entityManager = entityManager;
    }

    private void checkParameters(Reader reader) {
        if (reader == null) {
            throw new IllegalArgumentException("Reader cannot be null.");
        }
        if (reader.getFirstName() == null) {
            throw new IllegalArgumentException("Reader's first name cannot be null.");
        }
        if (reader.getSurname() == null) {
            throw new IllegalArgumentException("Reader's surname cannot be null.");
        }
        if (reader.getBirthNumber() == null) {
            throw new IllegalArgumentException("Reader's birth number cannot be null.");
        }
        if (reader.getAddress() == null) {
            throw new IllegalArgumentException("Reader's first name cannot be null.");
        }
        if (reader.getEmail() == null) {
            throw new IllegalArgumentException("Reader's email cannot be null.");
        }
        if (reader.getFirstName().compareTo("") == 0) {
            throw new IllegalArgumentException("Reader's first name cannot be empty.");
        }
        if (reader.getSurname().compareTo("") == 0) {
            throw new IllegalArgumentException("Reader's surname cannot be empty.");
        }
        if (reader.getBirthNumber().compareTo("") == 0) {
            throw new IllegalArgumentException("Reader's birth number cannot be empty.");
        }
        if (reader.getAddress().compareTo("") == 0) {
            throw new IllegalArgumentException("Reader's address cannot be empty.");
        }
        if (reader.getEmail().compareTo("") == 0) {
            throw new IllegalArgumentException("Reader's email cannot be empty.");
        }
    }

    public Reader createReader(Reader reader) {
        checkParameters(reader);
        if (reader.getId() != null) {
            throw new IllegalArgumentException("Reader id is already set.");
        }

        //searching whether UNIQUE constraints on columns birthNumber or email are not to be violated
        if (!(findReaderByBirthNumber(reader.getBirthNumber()) == null)) {
            throw new IllegalArgumentException("There is already a reader with such birth number.");
        }

        if (!(findReaderByEmail(reader.getEmail()) == null)) {
            throw new IllegalArgumentException("There is already a reader with such email.");
        }

        entityManager.persist(reader);
        return reader;
    }

    public List<Reader> findAllReaders() {
        List<Reader> result = entityManager.createQuery("SELECT e FROM Reader e", Reader.class).getResultList();
        return result;
    }
    
    public List<Reader> findReaderByFull(String firstName, String surname, String email) {
        if (firstName == null) {
            firstName = "";
        }
        if (surname == null) {
            surname = "";
        }
        if (email == null) {
            email = "";
        }

        return entityManager.createQuery("SELECT e FROM Reader e WHERE e.firstName LIKE '%"
                + firstName + "%' AND e.surname LIKE '%" + surname + "%' AND e.email LIKE '%"
                + email + "%'", Reader.class).getResultList();
    }

    public Reader findReaderById(Long id) {
        if (id == null) {
            throw new IllegalArgumentException("Id cannot be null.");
        }
        if (id.intValue() <= 0) {
            throw new IllegalArgumentException("Id must be positive.");
        }

        Reader reader = entityManager.find(Reader.class, id);
        return reader;
    }

    public List<Reader> findReaderByName(String firstName, String surname) {
        if (firstName == null) {
            throw new IllegalArgumentException("First name cannot be null.");
        }
        if (surname == null) {
            throw new IllegalArgumentException("Surname cannot be null.");
        }
        if (firstName.compareTo("") == 0) {
            throw new IllegalArgumentException("First name cannot be empty.");
        }
        if (surname.compareTo("") == 0) {
            throw new IllegalArgumentException("Surname cannot be empty.");
        }

        return entityManager.createQuery("SELECT e FROM Reader e WHERE e.firstName = '"
                + firstName + "' AND e.surname = '" + surname + "'", Reader.class).getResultList();
    }

    public Reader findReaderByBirthNumber(String birthNumber) {
        if (birthNumber == null) {
            throw new IllegalArgumentException("Birth number cannot be null.");
        }
        if (birthNumber.compareTo("") == 0) {
            throw new IllegalArgumentException("Birth number cannot be empty.");
        }

        String query = "SELECT e FROM Reader e WHERE e.birthNumber = '" + birthNumber + "'";
        try {
            return entityManager.createQuery(query, Reader.class).getSingleResult();
        } catch (NoResultException nre) {
            return null;
        } catch (NonUniqueResultException nure) {
            throw new NonUniqueResultException("There are more readers with this birth number: " + birthNumber);
        }
    }

    public Reader findReaderByEmail(String email) {
        if (email == null) {
            throw new IllegalArgumentException("Email cannot be null.");
        }
        if (email.compareTo("") == 0) {
            throw new IllegalArgumentException("Email cannot be empty.");
        }

        String query = "SELECT e FROM Reader e WHERE e.email = '" + email + "'";
        try {
            return entityManager.createQuery(query, Reader.class).getSingleResult();
        } catch (NoResultException nre) {
            return null;
        } catch (NonUniqueResultException nure) {
            throw new NonUniqueResultException("There are more readers with this email: " + email);
        }
    }

    public void updateReader(Reader reader) {
        checkParameters(reader);

        //searching whether UNIQUE constraints on columns birthNumber or email are not to be violated
        if (!(findReaderByBirthNumber(reader.getBirthNumber()) == null)
                && !(findReaderByBirthNumber(reader.getBirthNumber())).equals(reader)) {
            throw new IllegalArgumentException("There is already another reader with such birth number.");
        }

        if (!(findReaderByEmail(reader.getEmail()) == null)
                && !(findReaderByEmail(reader.getEmail())).equals(reader)) {
            throw new IllegalArgumentException("There is already another reader with such email.");
        }

        Reader reader2 = findReaderById(reader.getId());
        if (reader2 != null) {
            reader2.setFirstName(reader.getFirstName());
            reader2.setSurname(reader.getSurname());
            reader2.setBirthNumber(reader.getBirthNumber());
            reader2.setEmail(reader.getEmail());
            reader2.setAddress(reader.getAddress());
            reader2.setTelephoneNumber(reader.getTelephoneNumber());
            reader2.setPassword(reader.getPassword());
        } else {
            throw new IllegalArgumentException("Unknown reader id: " + reader.getId());
        }
        entityManager.merge(reader2);
    }

    public void deleteReader(Reader reader) {
        if (reader == null) {
            throw new IllegalArgumentException("Deleted reader cannot be null");
        }
        if (reader.getId() == null) {
            throw new IllegalArgumentException("Unknown reader - has null id.");
        }

        Reader r = entityManager.merge(reader);
        entityManager.remove(r);
    }
      

      public Reader authentize(String email, String password){
            if(email == null || password == null) return null;
                Reader reader = findReaderByEmail(email);
                if(reader == null) return null;
                if(!password.equals(reader.getPassword())){
                        return null;
                }
                return reader;
        }

}